/**
 * 渲染状态组件
 * 
 * 职责：
 * 1. 存储待应用到视图的渲染数据
 * 2. 使用脏标记跟踪哪些字段需要更新
 * 3. 减少命令队列的内存占用（命令只传递指令，不传递数据）
 * 
 * 设计理念：
 * - 命令只是"指令"，不携带大量数据对象
 * - 数据存储在组件中，命令通过 entityId 引用
 * - 使用脏标记避免不必要的更新
 * 
 * @author AI Assistant
 * @date 2025-12-02
 */

import { ecs } from "../../core/ecs/ECS";
import { Vec3, Color, SpriteFrame } from "cc";

/**
 * 脏标记接口
 */
interface DirtyFlags {
    position?: boolean;
    rotation?: boolean;
    scale?: boolean;
    visible?: boolean;
    active?: boolean;
    spriteColor?: boolean;
    spriteOpacity?: boolean;
    spriteFrame?: boolean;
    labelText?: boolean;
    labelColor?: boolean;
    animation?: boolean;
}

/**
 * 渲染状态组件
 * 
 * 使用方式：
 * ```typescript
 * // 1. 写入数据到组件
 * const renderState = entity.get(RenderStateComponent);
 * renderState.position = new Vec3(100, 200, 0);
 * renderState.markDirty('position');
 * 
 * // 2. 发送轻量级命令（不携带数据）
 * LogicCmd.updateRenderState(entity.eid);
 * 
 * // 3. 渲染系统从组件读取数据并应用
 * ```
 */
@ecs.register('RenderStateComponent')
export class RenderStateComponent extends ecs.Component {
    // ========== 变换数据 ==========
    
    /** 位置 */
    position: Vec3 = Vec3.ZERO.clone();
    
    /** 旋转（欧拉角） */
    rotation: Vec3 = Vec3.ZERO.clone();
    
    /** 缩放 */
    scale: Vec3 = Vec3.ONE.clone();
    
    // ========== 显示状态 ==========
    
    /** 是否可见 */
    visible: boolean = true;
    
    /** 是否激活 */
    active: boolean = true;
    
    // ========== 精灵数据 ==========
    
    /** 精灵颜色 */
    spriteColor: Color = Color.WHITE.clone();
    
    /** 精灵透明度 (0-255) */
    spriteOpacity: number = 255;
    
    /** 精灵帧 */
    spriteFrame: SpriteFrame | null = null;
    
    // ========== 标签数据 ==========
    
    /** 标签文本 */
    labelText: string = '';
    
    /** 标签颜色 */
    labelColor: Color = Color.WHITE.clone();
    
    // ========== 动画数据 ==========
    
    /** 动画名称 */
    animationName: string = '';
    
    /** 动画是否循环 */
    animationLoop: boolean = false;
    
    /** 动画状态 */
    animationState: 'play' | 'stop' | 'pause' | 'none' = 'none';
    
    // ========== 脏标记 ==========
    
    /** 标记哪些字段需要更新 */
    private dirtyFlags: DirtyFlags = {};
    
    /**
     * 标记字段为脏
     * @param field 字段名
     */
    markDirty(field: keyof DirtyFlags): void {
        this.dirtyFlags[field] = true;
    }
    
    /**
     * 标记多个字段为脏
     * @param fields 字段名数组
     */
    markDirtyFields(fields: (keyof DirtyFlags)[]): void {
        for (const field of fields) {
            this.dirtyFlags[field] = true;
        }
    }
    
    /**
     * 标记所有字段为脏
     */
    markAllDirty(): void {
        this.dirtyFlags = {
            position: true,
            rotation: true,
            scale: true,
            visible: true,
            active: true,
            spriteColor: true,
            spriteOpacity: true,
            spriteFrame: true,
            labelText: true,
            labelColor: true,
            animation: true
        };
    }
    
    /**
     * 检查字段是否脏
     * @param field 字段名
     */
    isDirty(field: keyof DirtyFlags): boolean {
        return this.dirtyFlags[field] === true;
    }
    
    /**
     * 检查是否有任何脏字段
     */
    hasAnyDirty(): boolean {
        return Object.keys(this.dirtyFlags).length > 0;
    }
    
    /**
     * 获取所有脏字段
     */
    getDirtyFields(): (keyof DirtyFlags)[] {
        return Object.keys(this.dirtyFlags).filter(
            key => this.dirtyFlags[key as keyof DirtyFlags]
        ) as (keyof DirtyFlags)[];
    }
    
    /**
     * 清除单个脏标记
     * @param field 字段名
     */
    clearDirty(field: keyof DirtyFlags): void {
        delete this.dirtyFlags[field];
    }
    
    /**
     * 清除所有脏标记
     */
    clearAllDirty(): void {
        this.dirtyFlags = {};
    }
    
    // ========== 便捷方法 ==========
    
    /**
     * 设置位置并标记为脏
     */
    setPosition(x: number, y: number, z: number = 0): void {
        this.position.set(x, y, z);
        this.markDirty('position');
    }
    
    /**
     * 设置位置（Vec3）并标记为脏
     */
    setPositionVec3(position: Vec3): void {
        this.position.set(position);
        this.markDirty('position');
    }
    
    /**
     * 设置旋转并标记为脏
     */
    setRotation(x: number, y: number, z: number): void {
        this.rotation.set(x, y, z);
        this.markDirty('rotation');
    }
    
    /**
     * 设置缩放并标记为脏
     */
    setScale(x: number, y: number, z: number = 1): void {
        this.scale.set(x, y, z);
        this.markDirty('scale');
    }
    
    /**
     * 设置统一缩放并标记为脏
     */
    setUniformScale(scale: number): void {
        this.scale.set(scale, scale, scale);
        this.markDirty('scale');
    }
    
    /**
     * 设置可见性并标记为脏
     */
    setVisible(visible: boolean): void {
        this.visible = visible;
        this.markDirty('visible');
    }
    
    /**
     * 设置激活状态并标记为脏
     */
    setActive(active: boolean): void {
        this.active = active;
        this.markDirty('active');
    }
    
    /**
     * 设置精灵颜色并标记为脏
     */
    setSpriteColor(color: Color): void {
        this.spriteColor.set(color);
        this.markDirty('spriteColor');
    }
    
    /**
     * 设置精灵透明度并标记为脏
     */
    setSpriteOpacity(opacity: number): void {
        this.spriteOpacity = opacity;
        this.markDirty('spriteOpacity');
    }
    
    /**
     * 设置精灵帧并标记为脏
     */
    setSpriteFrame(spriteFrame: SpriteFrame | null): void {
        this.spriteFrame = spriteFrame;
        this.markDirty('spriteFrame');
    }
    
    /**
     * 设置标签文本并标记为脏
     */
    setLabelText(text: string): void {
        this.labelText = text;
        this.markDirty('labelText');
    }
    
    /**
     * 设置标签颜色并标记为脏
     */
    setLabelColor(color: Color): void {
        this.labelColor.set(color);
        this.markDirty('labelColor');
    }
    
    /**
     * 播放动画并标记为脏
     */
    playAnimation(name: string, loop: boolean = false): void {
        this.animationName = name;
        this.animationLoop = loop;
        this.animationState = 'play';
        this.markDirty('animation');
    }
    
    /**
     * 停止动画并标记为脏
     */
    stopAnimation(): void {
        this.animationState = 'stop';
        this.markDirty('animation');
    }
    
    /**
     * 暂停动画并标记为脏
     */
    pauseAnimation(): void {
        this.animationState = 'pause';
        this.markDirty('animation');
    }
    
    // ========== 生命周期 ==========
    
    /**
     * 重置组件
     */
    reset(): void {
        this.position.set(Vec3.ZERO);
        this.rotation.set(Vec3.ZERO);
        this.scale.set(Vec3.ONE);
        this.visible = true;
        this.active = true;
        this.spriteColor.set(Color.WHITE);
        this.spriteOpacity = 255;
        this.spriteFrame = null;
        this.labelText = '';
        this.labelColor.set(Color.WHITE);
        this.animationName = '';
        this.animationLoop = false;
        this.animationState = 'none';
        this.clearAllDirty();
    }
    
    /**
     * 调试信息
     */
    debugInfo(): string {
        const dirtyFields = this.getDirtyFields();
        return `RenderStateComponent: ${dirtyFields.length} dirty fields [${dirtyFields.join(', ')}]`;
    }
}

